CloudWatchアラームとSNSで日本語の件名・本文のメールを送るためのCloudFormationテンプレートを作ってみた
データアナリティクス事業本部の鈴木です。
今回はCloudWatchアラームの状態遷移が起きた際に日本語の件名・本文のメールをSNSから送信する方法を調べました。また、構成をデプロイできるようCloudFormationテンプレートを作成したのでご紹介します。
やりたかったこと
CloudWatchアラームがアラーム状態に遷移した時に、日本語の件名・本文のメールをSNSから送信したいです。
例えば以下のような通知です。
調べていたところ、以下の二つの記事がとても参考になり、組み合わせてCloudFormationテンプレートにしてみました。
構成
CloudWatchアラームがアラーム状態に遷移するイベントをEventBridgeで検知し、SNSでメール通知します。SNSをEventBridgeのターゲットに直接指定すると件名が指定できないので、Step Functionsを介して呼び出します。[2]
作成したテンプレート
今回は、SQSでデッドレターキューを運用しているとして、キューにメッセージが入った際の通知を想定します。
以下のような構成です。
分かりやすさのため、まずデッドレターキューのテンプレートを記載します。
AWSTemplateFormatVersion: 2010-09-09 Description: SQS Standard Queue Parameters: QueueName: Description: Name for queue Type: String Resources: ################################ # イベント作成用のサンプルのリソース # ################################ ## SQSキュー SQSQueue: Type: AWS::SQS::Queue Properties: MessageRetentionPeriod: 1209600 QueueName: !Sub ${QueueName} VisibilityTimeout: 120
続いて、今回作成した通知用のテンプレートです。
AWSTemplateFormatVersion: 2010-09-09 Description: Alarm & SNS notification Parameters: SNSTopicName: Description: SNSTopicName for Alarm Type: String NotificateDestinationEmail: Description: Destination Email for SNS Type: String QueueName: Description: Name for queue Type: String Resources: ################# # 通知用のリソース # ################# ## CloudWatch アラーム SQSAlarm: Type: AWS::CloudWatch::Alarm Properties: AlarmName: !Sub ${QueueName}-alerm ComparisonOperator: GreaterThanThreshold DatapointsToAlarm: 1 EvaluationPeriods: 1 Threshold: 0 Namespace: AWS/SQS Dimensions: - Name: QueueName Value: !Sub ${QueueName} MetricName: ApproximateNumberOfMessagesVisible Period: 60 Statistic: Maximum TreatMissingData: notBreaching ## 件名カスタマイズ用のステートマシン SNSStateMachine: Type: "AWS::StepFunctions::StateMachine" Properties: DefinitionString: !Sub |- { "StartAt": "PublishSns", "States": { "PublishSns": { "Type": "Task", "Resource": "arn:aws:states:::sns:publish", "Parameters": { "TopicArn": "arn:aws:sns:${AWS::Region}:${AWS::AccountId}:${SNSTopicName}", "Message.$": "$.message", "Subject.$": "$.subject" }, "End": true } } } RoleArn: !GetAtt [ PublishRole, Arn ] ## SNSトピック SnsTopic: Type: AWS::SNS::Topic Properties: TopicName: !Sub ${SNSTopicName} Subscription: - Endpoint: !Sub ${NotificateDestinationEmail} Protocol: email ## EventBridge AlarmEvent: Type: AWS::Events::Rule Properties: Description: String EventPattern: !Sub | { "source": ["aws.cloudwatch"], "detail-type": ["CloudWatch Alarm State Change"], "resources": [{"prefix": "arn:aws:cloudwatch:${AWS::Region}:${AWS::AccountId}:alarm:${QueueName}-alerm"}], "detail": {"state": {"value": ["ALARM"]}} } Targets: - Arn: !Ref SNSStateMachine Id: step-function RoleArn: !GetAtt [ StateMachineExecuteRole, Arn ] InputTransformer: InputPathsMap: "Account": "$.account" "AlarmName": "$.detail.alarmName" "MetricsName": "$.detail.configuration.metrics[0].metricStat.metric.name" "Reason": "$.detail.state.reason" "Time": "$.time" InputTemplate: | { "subject": "デッドレターキューにメッセージが入りました", "message": "AWSアカウントID: \"<Account>\" \n 発生時間(GMT): \"<Time>\" \n 発生アラーム名: \"<AlarmName>\" \n 発生メトリクス: \"<MetricsName>\" \n\n 理由: \"<Reason>\"" } # Role PublishRole: Type: "AWS::IAM::Role" Properties: AssumeRolePolicyDocument: Version: "2012-10-17" Statement: - Effect: "Allow" Principal: Service: - states.amazonaws.com Action: "sts:AssumeRole" Path: "/" Policies: - PolicyName: SNSPublish PolicyDocument: Statement: - Effect: Allow Resource: - !Ref SnsTopic Action: - sns:Publish StateMachineExecuteRole: Type: "AWS::IAM::Role" Properties: AssumeRolePolicyDocument: Version: "2012-10-17" Statement: - Effect: "Allow" Principal: Service: - events.amazonaws.com Action: "sts:AssumeRole" Path: "/" Policies: - PolicyName: StateMachineExecute PolicyDocument: Statement: - Effect: Allow Resource: - !Ref SNSStateMachine Action: - states:StartExecution
テンプレート作成時のポイントは以下になります。
- アラームの設定を修正することで、監視対象のメトリクスや状態に遷移する条件を調整することができます。今回は作成しておいたSQSのキューの
ApproximateNumberOfMessagesVisible
メトリクスを見るように設定しています。(24〜36行目) - 通知先の設定はSNS Topicの
Subscription
にて行います。今回はパラメータで渡した1つのEmailを設定するようにしています。(65〜67行目) - EventBridgeのルールの
EventPattern
で監視対象のリソースとイベント内容を指定しています。(74〜80行目) - 日本語の件名およびメッセージはEventBridgeのルールの
InputTemplate
にて設定しています。Step Functionsを挟んだ場合、本文で改行したい場合はテンプレートの文字列に\n
を入れることで改行ができました。(92〜96行目)
やってみる
1. CloudFormationでデプロイする
上記のテンプレートをCloudFormationからデプロイしておきます。
デプロイが完了すると各リソースが作成されます。また、SNSからメール通知されるアドレスに、サブスクリプションの承認依頼メールが届くので、承認しておきます。
例えば、作成したアラームは以下のようになっており、これがアラーム状態になると、EventBridge以降が稼働してメール送信までを行います。
EventBridgeのルールの画面からは、ターゲットおよび入力トランスフォーマーの設定が期待通りにできていることが分かります。
2. アラーム状態に遷移させてメール通知する
アラームをアラーム状態に遷移させて、メールが飛ぶことを確認します。
まず、作成したキューをコンソールから選択します。
メッセージを送受信
を開きます。
適当なメッセージをキューに送信しておきます。
しばらくして、アラームがアラーム状態になることを確認します。
SNSトピックに登録したメールを確認すると、通知が飛んできていることを確認できました。
最後に
今回はCloudWatchアラームの状態遷移と関連づけて日本語の件名・本文のメールをSNSから送信する方法を調べ、その構成とCloudFormationテンプレート例をご紹介しました。
実際の運用では、通知を日本語で行いたいケースが多々あると思いますが、EventBridgeルールの入力トランスフォーマーに日本語のテンプレートを設定しておき、Step Functionsを介してSNSに渡すことで簡単に日本語のメールが設定できるのはとてもよいですね。
参考になりましたら幸いです。
参考
CloudFormation以外でのデプロイ方法や、各機能の詳細も分かるので、ぜひ併せてご確認ください。